package com.yupi.yuoj.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import com.yupi.yuoj.common.ErrorCode;
import com.yupi.yuoj.exception.BusinessException;
import com.yupi.yuoj.judge.JudgeService;
import com.yupi.yuoj.judge.codesandbox.model.JudgeInfo;
import com.yupi.yuoj.model.dto.question.QuestionQueryRequest;
import com.yupi.yuoj.model.dto.questionsubmit.QuestionSubmitAddRequest;
import com.yupi.yuoj.model.entity.Question;
import com.yupi.yuoj.model.entity.QuestionSubmit;
import com.yupi.yuoj.model.entity.User;
import com.yupi.yuoj.model.enums.JudgeInfoMessageEnum;
import com.yupi.yuoj.model.enums.QuestionSubmitLanguageEnum;
import com.yupi.yuoj.model.enums.QuestionSubmitStatusEnum;
import com.yupi.yuoj.model.vo.QuestionLanguageStatus;
import com.yupi.yuoj.model.vo.QuestionVO;
import com.yupi.yuoj.service.QuestionService;
import com.yupi.yuoj.service.QuestionSubmitService;
import com.yupi.yuoj.mapper.QuestionSubmitMapper;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
* @author 李胜
* @description 针对表【question_submit(题目提交)】的数据库操作Service实现
* @createDate 2025-08-27 16:19:26
*/
@Service
public class QuestionSubmitServiceImpl extends ServiceImpl<QuestionSubmitMapper, QuestionSubmit>
    implements QuestionSubmitService{

    @Resource
    private QuestionService questionService;

    @Resource
    @Lazy
    private JudgeService judgeService;

    @Autowired
    private QuestionSubmitMapper questionSubmitMapper;

    @Override
    public long doQuestionSubmit(QuestionSubmitAddRequest questionSubmitAddRequest, User loginUser) {
        // 校验编程语言是否合法
        String language = questionSubmitAddRequest.getLanguage();
        QuestionSubmitLanguageEnum enumByValue = QuestionSubmitLanguageEnum.getEnumByValue(language);
        if (enumByValue == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "编程语言错误");
        }
        Long questionId = questionSubmitAddRequest.getQuestionId();
        // 判断题目是否存在
        Question question = questionService.getById(questionId);
        if (question == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        Long userId = loginUser.getId();
        QuestionSubmit questionSubmit = new QuestionSubmit();
        questionSubmit.setLanguage(language);
        questionSubmit.setCode(questionSubmitAddRequest.getCode());
        questionSubmit.setQuestionId(questionId);
        questionSubmit.setUserId(userId);
        // 设置初始状态
        questionSubmit.setJudgeInfo("{}");
        questionSubmit.setStatus(QuestionSubmitStatusEnum.WAITING.getValue());
        boolean result = this.save(questionSubmit);
        if (!result) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "数据插入失败");
        }
        Long questionSubmitId = questionSubmit.getId();
        // 执行判题服务
/*
        CompletableFuture.runAsync(()->{
            judgeService.doJudge(questionSubmitId);
        });
*/
        judgeService.doJudge(questionSubmitId);
        return questionSubmitId;
    }

    /**
     * 过题数+尝试数
     * @param userId
     * @return
     */
    @Override
    public long questionDoStatusALL(Long userId) {
        QueryWrapper<QuestionSubmit> questionSubmitQueryWrapper = new QueryWrapper<>();
        questionSubmitQueryWrapper.select("DISTINCT questionId");
        questionSubmitQueryWrapper.eq("userId", userId);
        questionSubmitQueryWrapper.eq("status", QuestionSubmitStatusEnum.SUCCEED.getValue());
        Long count = questionSubmitMapper.selectCount(questionSubmitQueryWrapper);
        return count;
    }

    /**
     * 总过题数
     * @param userId
     * @return
     */
    @Override
    public long questionDoStatusAC(Long userId) {
        QueryWrapper<QuestionSubmit> questionSubmitQueryWrapper = new QueryWrapper<>();
        questionSubmitQueryWrapper.eq("userId", userId);
        List<QuestionSubmit> questionSubmits = questionSubmitMapper.selectList(questionSubmitQueryWrapper);
        Gson gson = new Gson();
        Map<Long, Long> acDistinctSubmit = questionSubmits.stream().filter(questionSubmit -> {
            String judgeInfoStr = questionSubmit.getJudgeInfo();
            if(!questionSubmit.getStatus().equals(QuestionSubmitStatusEnum.SUCCEED.getValue())) {
                return false;
            }
            JudgeInfo judgeInfo = gson.fromJson(judgeInfoStr, JudgeInfo.class);
            Optional<String> judgeInfoMessage = Optional.ofNullable(judgeInfo.getMessage());
            return judgeInfoMessage.orElse("").equals(JudgeInfoMessageEnum.ACCEPTED.getValue());
        }).collect(Collectors.groupingBy(
                QuestionSubmit::getQuestionId,
                Collectors.counting()
        ));
        return acDistinctSubmit.size();
    }

    /**
     * 统计不同语言的过题数
     * @param userId
     * @return
     */
    @Override
    public List<QuestionLanguageStatus> questionLanguageStatus(Long userId) {
        LambdaQueryWrapper<QuestionSubmit> questionSubmitLambdaQueryWrapper = new LambdaQueryWrapper<>();
        questionSubmitLambdaQueryWrapper.eq(QuestionSubmit::getUserId, userId);
        List<QuestionSubmit> questionSubmits = questionSubmitMapper.selectList(questionSubmitLambdaQueryWrapper);
        Gson gson = new Gson();
        Map<String, Set<Long>> passGroup = questionSubmits.stream().filter(questionSubmit -> {
            String judgeInfoStr = questionSubmit.getJudgeInfo();
            if (!questionSubmit.getStatus().equals(QuestionSubmitStatusEnum.SUCCEED.getValue())) {
                return false;
            }
            JudgeInfo judgeInfo = gson.fromJson(judgeInfoStr, JudgeInfo.class);
            Optional<String> judgeInfoMessage = Optional.ofNullable(judgeInfo.getMessage());
            return judgeInfoMessage.orElse("").equals(JudgeInfoMessageEnum.ACCEPTED.getValue());
        }).collect(Collectors.groupingBy(QuestionSubmit::getLanguage, Collectors.mapping(QuestionSubmit::getQuestionId, Collectors.toSet())));
        List<QuestionLanguageStatus> res = new ArrayList<>();
        for(Map.Entry<String, Set<Long>> mp:passGroup.entrySet()) {
            res.add(new QuestionLanguageStatus(QuestionSubmitLanguageEnum.getEnumByValue(mp.getKey()).getText(), mp.getValue().size()));
        }
        res.sort((a, b) -> Long.compare(b.getPassNum(), a.getPassNum()));
        return res;
    }
}




